package com.zjsd.sqeybusiness.lakala;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.zjsd.sqeybusiness.domain.*;
import com.zjsd.sqeybusiness.mapper.*;
import com.zjsd.sqeybusiness.service.PayBaseService;
import com.zjsd.sqeybusiness.utils.UniqueIdGenerator;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.security.*;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Service
public class LaKaLaPayService  implements PayBaseService {
    /**
     * 字符集固定 utf-8
     */
    public static final String ENCODING = "utf-8";
    /**
     * API schema ,固定 LKLAPI-SHA256withRSA
     */
    public final static String SCHEMA = "LKLAPI-SHA256withRSA";
    /**
     * 接入 appid
     */
    public static final String appid = "OP10000456";
    /**
     * 商户证书序列号，和商户私钥对应
     */
    public static final String mchSerialNo = "01948ce4ba8f";

    // 商户号
    //public static final String marchentNo = "82245107311022H";
    public static final String marchentNo = "822452053110MQN";
    //专业化扫码终端号
    public static final String termNo = "M6424762";
    /**
     * 商户证书私钥，用于请求签名
     */
    public static final String merchantPrivateKeyPath = "/api_private_key.pem";
    /**
     * 拉卡拉公钥证书，用于response签名验证，务必区分测试环境和生产环境证书
     */
    public static final String lklCertificatePath = "/lkl-gy.cer";
    /**
     * api请求地址
     */
    public final static String apiUrl = "https://test.wsmsd.cn/sit";
    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final SecureRandom RANDOM = new SecureRandom();
    public final static  String ORDER_PAY_URL = "https://s2.lakala.com/api/v3/ccss/counter/order/special_create";
    public final static  String MINI_ORDER_PAY_URL = "https://s2.lakala.com/api/v3/labs/trans/preorder";
    public final static  String ORDER_REFUND_URL = "https://s2.lakala.com/api/v3/rfd/refund_front/refund";
    public final static  String MINI_ORDER_REFUND_URL = "https://s2.lakala.com/api/v3/labs/relation/refund";
    public final static  String ORDER_QUERY_URL = "https://s2.lakala.com/api/v3/ccss/counter/order/query";
    //public final static  String PAY_NOTIFY_URL = "https://sqeyapp.abcsale.cn/sqeyApp/zjsd/agency/kthy/lakalaPayNotify";
    //public final static  String REFUND_NOTIFY_URL = "https://sqeyapp.abcsale.cn/sqeyApp/zjsd/agency/kthy/lakalaPayRefundNotify";
    //支付回调
    public final static  String PAY_NOTIFY_URL = "https://sqeybusiness.abcsale.cn/sqeybusiness/mobile/lakalaPayNotify";
    public final static  String MINI_PAY_NOTIFY_URL = "https://sqeybusiness.abcsale.cn/sqeybusiness/mobile/lakalaMiniPayNotify";
    //退款回调
    public final static  String REFUND_NOTIFY_URL = "http://sqeybusiness.abcsale.cn/sqeybusiness/lakalaPayRefundNotify";
    @Autowired
    private PayorderinfoMapper payorderinfoMapper;
    @Autowired
    private PayreturninfoMapper payreturninfoMapper;
    @Autowired
    private OrderinfoMapper orderinfoMapper;
    @Autowired
    private SjinfoMapper sjinfoMapper ; //商户信息
    @Autowired
    private AccountlocusMapper accountlocusMapper;
    @Autowired
    private HyinfoMapper hyinfoMapper;
    @Autowired
    private RechargeinfoMapper rechargeinfoMapper;
    @Override
    public Payorderinfo createOrder(String ywtype, Long orderId, String orderAmount, Long ma001, String remark, String openid, String ip) {
        String orderIdReq =  ywtype+"-"+orderId + "-" + UniqueIdGenerator.generate();
        String merchant_no = marchentNo ;
        String term_no = termNo;
        String total_amount = String.valueOf((new BigDecimal(orderAmount).multiply(new BigDecimal(100))).intValue());
        SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
        String order_efficient_time = sdf_ts.format(DateUtils.addDays(new Date(),7));
        String req_time = sdf_ts.format(new Date());
        String body = "{\n" +
                "    \"req_data\": {\n" +
                "        \"out_trade_no\": \""+orderIdReq+"\", \n" +
                "        \"merchant_no\": \""+merchant_no+"\", \n" +
                "        \"term_no\": \""+term_no+"\", \n" +
                "        \"account_type\": \"WECHAT\", \n" +
                "        \"trans_type\": \"51\", \n" +
                "        \"location_info\": {\n" +
                "            \"request_ip\": \""+ip+"\"\n" +
                "        },   "+
                "        \"total_amount\": \""+total_amount+"\", \n" +
                "        \"notify_url\": \""+MINI_PAY_NOTIFY_URL+"\", \n" +
                "        \"subject\": \""+remark+"\", \n" +
                "        \"acc_busi_fields\": {\n" +
                "            \"sub_appid\": \"wxd81a6bd295facda3\",\n" +
                "            \"user_id\": \""+openid+"\"\n" +
                "        }   "+
                "    }, \n" +
                "    \"version\": \"3.0\", \n" +
                "    \"req_time\": \""+req_time+"\"}";

        System.out.println("body  " + body);
        try {
            String authorization = getAuthorization(body);
            HttpResponse response = post(MINI_ORDER_PAY_URL, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                String err = "请求失败，statusCode  " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING);
                System.out.println(err);
                throw new CustomException(err);
            }

            String appid = getHeadValue(response, "Lklapi-Appid");
            String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
            String timestamp = getHeadValue(response, "Lklapi-Timestamp");
            String nonce = getHeadValue(response, "Lklapi-Nonce");
            String signature = getHeadValue(response, "Lklapi-Signature");
            String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
            System.out.println("responseStr  " + responseStr);
            String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
            //System.out.println("source  " + source);
            //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
            X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));
            boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
            if (verify) {
                System.out.println("验签成功");
                // TODO: 业务处理
                PayResult result = JSON.parseObject(responseStr, PayResult.class);
                if(!"BBS00000".equals(result.getCode())){
                    throw new CustomException(result.getMsg());
                }
                JSONObject jsonObject = JSON.parseObject(responseStr);
                JSONObject resp_data = jsonObject.getJSONObject("resp_data");
                JSONObject acc_resp_fields = resp_data.getJSONObject("acc_resp_fields");
                String sub_mch_id = acc_resp_fields.getString("sub_mch_id");

                String timeStamp = acc_resp_fields.getString("time_stamp");
                String nonceStr = acc_resp_fields.getString("nonce_str");
                String package1 = acc_resp_fields.getString("package");
                String signType = acc_resp_fields.getString("sign_type");
                String paySign = acc_resp_fields.getString("pay_sign");


                String payinfo = "{\n" +
                        "    \"timeStamp\": \""+timeStamp+"\",\n" +
                        "    \"nonceStr\": \""+nonceStr+"\",\n" +
                        "    \"package\": \""+package1+"\",\n" +
                        "    \"signType\": \""+signType+"\",\n" +
                        "    \"paySign\": \""+paySign+"\"\n" +
                        "  }";
                Payorderinfo payorderinfo = new Payorderinfo(); 
                //保存发起信息
                payorderinfo.setOrderid(orderId);
                payorderinfo.setPaychannel("5");
                payorderinfo.setCmid(sub_mch_id);
                payorderinfo.setYwddidlx(ywtype);//1、购买商机充值 2、会员充值 3、升级会员充值
                payorderinfo.setPaytype("W06");
                payorderinfo.setTrxamt(orderAmount);
                payorderinfo.setAcct(openid);
                payorderinfo.setRemark(remark);
                payorderinfo.setNotifyurl(PAY_NOTIFY_URL);
                payorderinfo.setCsurl(null);
                payorderinfo.setCusip(ip);
                //保存返回信息
                payorderinfo.setRetcode(String.valueOf(result.getCode()));
                payorderinfo.setRetmsg(result.getMsg());
                payorderinfo.setTrxid(result.getResp_data().getTrade_no());
                //payorderinfo.setChnltrxid(result.getResp_data().getTrade_no());
                payorderinfo.setReqsn(orderIdReq);
                payorderinfo.setPayinfo(payinfo);
                //payorderinfo.setPayinfo(result.getResp_data().getCounter_url());
                payorderinfo.setXdsj(new Date());
                payorderinfo.setZfstatus("1");
                payorderinfo.setMa001(ma001);
                payorderinfo.setIsmainbody("0");
                payorderinfoMapper.insertPayorderinfo(payorderinfo);
                return payorderinfo;

            } else {
                System.err.println("验签失败");
                throw new CustomException("验签失败");
            }

        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("下单出现异常，请联系经销商！");
        }
    }

    @Override
    public void lakalaMiniPayNotify(HttpServletRequest request,  HttpServletResponse response) throws IOException {

        //获取请求参数
        //JSONObject JSONParam = JSON.parseObject(jsonParam);
        try {

            // 读取请求体中的JSON数据
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String jsonBody = sb.toString();
            System.out.println("MinilakalaPayNotify======" + jsonBody);

            LakalaPayNotify lakalaPayNotify = JSON.parseObject(jsonBody, LakalaPayNotify.class);
            System.out.println("-----------------------------");

            //boolean verify = laKaLaPayService.verifyData(request,jsonBody);
            //System.out.println("verify======"+verify);
            String reqsn = lakalaPayNotify.getOut_trade_no();
            String state = lakalaPayNotify.getTrade_status();
            String tradeNo = lakalaPayNotify.getTrade_no();
            System.out.println("tradeNo:" + tradeNo );
            System.out.println("reqsn:" + reqsn );
            String payStatus = "";
            if("SUCCESS".equals(state)){
                payStatus = "1";
            }else{
                payStatus = "3";
            }
            //保存支付结果
            Payorderinfo payorderinfo = new Payorderinfo() ;
            payorderinfo.setReqsn(reqsn);
            payorderinfo.setTrxid(tradeNo);
            List<Payorderinfo> payorderinfoList = payorderinfoMapper.selectPayorderinfoList(payorderinfo);
            if(payorderinfoList != null && payorderinfoList.size() > 0){
                System.out.println("更新支付成功：");
                Payorderinfo payorderinfo1 = payorderinfoList.get(0);
                if(payorderinfo1 != null){
                    if("1".equals(payorderinfo1.getYwddidlx())){
                        Orderinfo orderinfo = orderinfoMapper.selectOrderinfoById(payorderinfo1.getOrderid());
                        if(orderinfo != null){
                            orderinfo.setZfzt(payStatus);
                            orderinfoMapper.updateOrderinfo(orderinfo);
                            if(orderinfo.getRechargeid() != null ){
                                Rechargeinfo rechargeinfo = rechargeinfoMapper.selectRechargeinfoById(orderinfo.getRechargeid());
                                if(rechargeinfo != null){
                                    rechargeinfo.setZfzt(payStatus);
                                    rechargeinfoMapper.updateRechargeinfo(rechargeinfo);
                                }
                            }
                            Hyinfo hyinfo = hyinfoMapper.selectHyinfoById(orderinfo.getHyid());
                            Sjinfo sjinfo = sjinfoMapper.selectSjinfoById(orderinfo.getSjid());
                            if(sjinfo != null){
                                orderinfo.setCgrphone(sjinfo.getCgrphone());
                                Long jdsl = sjinfo.getJdsl() != null ? sjinfo.getJdsl() : 0L;
                                jdsl = jdsl + orderinfo.getJdsl();
                                sjinfo.setJdsl(jdsl);
                                sjinfoMapper.updateSjinfo(sjinfo);
                                //先记录充值
                                Accountlocus accountlocus = new Accountlocus();
                                accountlocus.setHyid(hyinfo.getHyid());
                                accountlocus.setSjid(sjinfo.getSjid());
                                accountlocus.setCzsj(new Date());
                                accountlocus.setHyname(hyinfo.getName());
                                accountlocus.setHyphone(hyinfo.getPhone());
                                accountlocus.setOpenid(hyinfo.getOpenid());
                                accountlocus.setWxname(hyinfo.getWxname());
                                BigDecimal zhye = hyinfo.getZhye() != null ? hyinfo.getZhye() : BigDecimal.ZERO;
                                BigDecimal bdqje = zhye ; // 充值前余额
                                zhye = zhye.add(orderinfo.getCzje() != null ? orderinfo.getCzje() : BigDecimal.ZERO);
                                BigDecimal bdhje = zhye ;
                                hyinfo.setZhye(zhye);
                                hyinfoMapper.updateHyinfo(hyinfo);
                                accountlocus.setBdqje(bdqje);
                                accountlocus.setBdhje(bdhje);
                                accountlocus.setSzlx("1");
                                accountlocus.setCzje(orderinfo.getCzje());
                                accountlocus.setCzje(orderinfo.getCzje());
                                accountlocus.setLsh(orderinfo.getOrderid() + "");
                                int i = accountlocusMapper.insertAccountlocus(accountlocus);
                                //再记录消费记录
                                Accountlocus accountlocus1 = new Accountlocus();
                                accountlocus1.setHyid(hyinfo.getHyid());
                                accountlocus1.setSjid(sjinfo.getSjid());
                                accountlocus1.setCzsj(new Date());
                                accountlocus1.setHyname(hyinfo.getName());
                                accountlocus1.setHyphone(hyinfo.getPhone());
                                accountlocus1.setOpenid(hyinfo.getOpenid());
                                accountlocus1.setWxname(hyinfo.getWxname());
                                accountlocus1.setCzje(orderinfo.getPrice());
                                accountlocus1.setSzlx("2");//消费
                                BigDecimal bdqje1 = hyinfo.getZhye() ;
                                BigDecimal bdhje1 = bdqje1.subtract(accountlocus1.getCzje());
                                hyinfo.setZhye(bdhje1);
                                hyinfoMapper.updateHyinfo(hyinfo);
                                accountlocus1.setBdqje(bdqje1);
                                accountlocus1.setBdhje(bdhje1);
                                i = accountlocusMapper.insertAccountlocus(accountlocus1);
                            }
                        }
                    }
                    //会员年费充值
                    if("2".equals(payorderinfo1.getYwddidlx())){
                        Rechargeinfo rechargeinfo = rechargeinfoMapper.selectRechargeinfoById(payorderinfo1.getOrderid());
                        if(rechargeinfo != null){
                            rechargeinfo.setZfzt(payStatus);
                            rechargeinfoMapper.updateRechargeinfo(rechargeinfo);
                            Hyinfo hyinfo = hyinfoMapper.selectHyinfoById(rechargeinfo.getHyid());
                            if(hyinfo != null){
                               BigDecimal zhye = hyinfo.getZhye() != null ? hyinfo.getZhye() : BigDecimal.ZERO;
                               BigDecimal bdqje = zhye ;
                               zhye = zhye.add(rechargeinfo.getCzje() != null ? rechargeinfo.getCzje() : BigDecimal.ZERO);
                               BigDecimal bdhje = zhye ;
                               hyinfo.setZhye(zhye);
                               hyinfoMapper.updateHyinfo(hyinfo);
                               BigDecimal bdqje1 = bdhje ;
                               zhye = zhye.subtract(rechargeinfo.getPrice() != null ? rechargeinfo.getPrice():BigDecimal.ZERO);
                               BigDecimal bdhje1 = zhye ;
                               if(zhye.compareTo(BigDecimal.ZERO) >= 0){
                                   hyinfo.setZhye(zhye);
                                   hyinfo.setHydjname(rechargeinfo.getHydjname());
                                   hyinfo.setHydjid(rechargeinfo.getHydjid());
                                   Date czsj = rechargeinfo.getCzsj();
                                   hyinfo.setKsrq(czsj);
                                   hyinfo.setJsrq(DateUtils.addYears(hyinfo.getKsrq(),1));
                                   hyinfoMapper.updateHyinfo(hyinfo);
                               }

                                //先记录充值
                                Accountlocus accountlocus = new Accountlocus();
                                accountlocus.setHyid(hyinfo.getHyid());
                                accountlocus.setCzsj(new Date());
                                accountlocus.setDzje(rechargeinfo.getCzje());
                                accountlocus.setHyname(hyinfo.getName());
                                accountlocus.setHyphone(hyinfo.getPhone());
                                accountlocus.setOpenid(hyinfo.getOpenid());
                                accountlocus.setWxname(hyinfo.getWxname());
                                accountlocus.setBdqje(bdqje);
                                accountlocus.setBdhje(bdhje);
                                accountlocus.setSzlx("1");
                                accountlocus.setCzje(rechargeinfo.getCzje());
                                accountlocus.setLsh(rechargeinfo.getRechargeid() + "");
                                int i = accountlocusMapper.insertAccountlocus(accountlocus);
                                if(zhye.compareTo(BigDecimal.ZERO) >= 0){
                                    Accountlocus accountlocus1 = new Accountlocus();
                                    accountlocus1.setHyid(hyinfo.getHyid());
                                    accountlocus1.setCzsj(new Date());
                                    accountlocus1.setDzje(rechargeinfo.getPrice());
                                    accountlocus1.setHyname(hyinfo.getName());
                                    accountlocus1.setHyphone(hyinfo.getPhone());
                                    accountlocus1.setOpenid(hyinfo.getOpenid());
                                    accountlocus1.setWxname(hyinfo.getWxname());
                                    accountlocus1.setCzje(rechargeinfo.getPrice());
                                    accountlocus1.setSzlx("2");//消费
                                    accountlocus1.setBdqje(bdqje1);
                                    accountlocus1.setBdhje(bdhje1);
                                    i = accountlocusMapper.insertAccountlocus(accountlocus1);
                                }
                            }
                        }
                    }
                    //简单的会员充值
                    if("3".equals(payorderinfo1.getYwddidlx())){
                        Rechargeinfo rechargeinfo = rechargeinfoMapper.selectRechargeinfoById(payorderinfo1.getOrderid());
                        if(rechargeinfo != null){
                            rechargeinfo.setZfzt(payStatus);
                            rechargeinfoMapper.updateRechargeinfo(rechargeinfo);
                            Hyinfo hyinfo = hyinfoMapper.selectHyinfoById(rechargeinfo.getHyid());
                            if(hyinfo != null){
                                BigDecimal zhye = hyinfo.getZhye() != null ? hyinfo.getZhye() : BigDecimal.ZERO;
                                BigDecimal bdqje = zhye ;
                                zhye = zhye.add(rechargeinfo.getDzje() != null ? rechargeinfo.getDzje() : BigDecimal.ZERO);
                                BigDecimal bdhje = zhye ;
                                hyinfo.setZhye(zhye);
                                hyinfoMapper.updateHyinfo(hyinfo);
                                //先记录充值
                                Accountlocus accountlocus = new Accountlocus();
                                accountlocus.setHyid(hyinfo.getHyid());
                                accountlocus.setCzsj(new Date());
                                accountlocus.setDzje(rechargeinfo.getCzje());
                                accountlocus.setHyname(hyinfo.getName());
                                accountlocus.setHyphone(hyinfo.getPhone());
                                accountlocus.setOpenid(hyinfo.getOpenid());
                                accountlocus.setWxname(hyinfo.getWxname());
                                accountlocus.setBdqje(bdqje);
                                accountlocus.setBdhje(bdhje);
                                accountlocus.setSzlx("1");
                                accountlocus.setCzje(rechargeinfo.getDzje());
                                accountlocus.setLsh(rechargeinfo.getRechargeid() + "");
                                int i = accountlocusMapper.insertAccountlocus(accountlocus);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            response.getOutputStream().write("SUCCESS".getBytes());
            response.flushBuffer();
        }

    }


    /**
     * 拉卡拉-退款成功回调
     * @param response
     */
    //@RequestMapping(value = "lakalaPayRefundNotify", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    //@ResponseBody
    @Override
    public void lakalaPayRefundNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取请求参数
        //JSONObject JSONParam = JSON.parseObject(jsonParam);
        try {
            // 读取请求体中的JSON数据
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String jsonBody = sb.toString();
            LakalaPayNotify lakalaPayNotify = JSON.parseObject(jsonBody, LakalaPayNotify.class);
            System.out.println("-----------------------------");
            String refundno = lakalaPayNotify.getOut_trade_no();
            String state = lakalaPayNotify.getTrade_status();
            String refundStatus ="";
            if("SUCCESS".equals(state)){
                refundStatus = "1";
            }else{
                refundStatus = "2";
            }
            Payreturninfo payreturninfo = new Payreturninfo();
            payreturninfo.setReturnid(null);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            response.getOutputStream().write("SUCCESS".getBytes());
            response.flushBuffer();
        }

    }

    /**
     * 拉卡拉-支付成功回调
     * @param response
     */
    public void lakalaPayNotify(HttpServletRequest request,  HttpServletResponse response) throws IOException {

        //获取请求参数
        //JSONObject JSONParam = JSON.parseObject(jsonParam);
        try {
            // 读取请求体中的JSON数据
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String jsonBody = sb.toString();
            System.out.println("lakalaPayNotify======" + jsonBody);
            LakalaPayNotify lakalaPayNotify = JSON.parseObject(jsonBody, LakalaPayNotify.class);
            System.out.println("-----------------------------");
            //boolean verify = laKaLaPayService.verifyData(request,jsonBody);
            //System.out.println("verify======"+verify);
           /*if(!verify){
              return;
           }*/
            String reqsn = lakalaPayNotify.getOut_order_no();
            String state = lakalaPayNotify.getOrder_status();
            String order_trade_info = lakalaPayNotify.getOrder_trade_info().getLog_no();
            String payStatus = "";
            if("2".equals(state)){
                payStatus = "2";
            }else{
                payStatus = "3";
            }
            //保存支付结果
            //service.savePayStatus(reqsn,payStatus,DateTools.format(new Date(),"yyyy-MM-dd HH:mm:ss"),order_trade_info);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            response.getOutputStream().write("SUCCESS".getBytes());
            response.flushBuffer();
        }
    }

    @Override
    public Payorderinfo createCodePay(Long ma001,Long orderId, String orderAmount, String remark, String ywtype,String callbackurl ) {
        String orderIdReq ="-"+ ywtype+"-"+orderId + "-" + UniqueIdGenerator.generate();
        String merchant_no = marchentNo ;
        String term_no = termNo;
        String total_amount = String.valueOf((new BigDecimal(orderAmount).multiply(new BigDecimal(100))).intValue());
        SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
        String order_efficient_time = sdf_ts.format(DateUtils.addDays(new Date(),7));
        String req_time = sdf_ts.format(new Date());
        String body = "{\n" +
                "    \"req_data\": {\n" +
                "        \"out_order_no\": \""+orderIdReq+"\", \n" +
                "        \"merchant_no\": \""+merchant_no+"\", \n" +
                "        \"term_no\": \""+term_no+"\", \n" +
              //  "        \"channel_id\": \"\", \n" +
                "        \"total_amount\": \""+total_amount+"\", \n" +
                "        \"order_efficient_time\": \""+order_efficient_time+"\", \n" +
                "        \"notify_url\": \""+PAY_NOTIFY_URL+"\", \n" +
                "        \"support_cancel\": \"0\", \n" +
                "        \"support_refund\": \"1\", \n" +
                "        \"support_repeat_pay\": \"0\", \n" +
                "        \"order_info\": \""+remark+"\", \n" +
                "        \"extend_info\": \"\", \n" +
                "        \"callback_url\": \""+callbackurl+"\"" +
                "    }, \n" +
                "    \"version\": \"3.0\", \n" +
                "    \"req_time\": \""+req_time+"\"}";

        try {
            String authorization = getAuthorization(body);
            System.out.println("body:  " + body);
            System.out.println("authorization:  " + authorization);

            HttpResponse response = post(ORDER_PAY_URL, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                String err = "请求失败，statusCode  " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING);
                System.out.println(err);
                throw new CustomException(err);
            }
            String appid = getHeadValue(response, "Lklapi-Appid");
            String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
            String timestamp = getHeadValue(response, "Lklapi-Timestamp");
            String nonce = getHeadValue(response, "Lklapi-Nonce");
            String signature = getHeadValue(response, "Lklapi-Signature");
            String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
            System.out.println("responseStr  " + responseStr);
            String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
            //System.out.println("source  " + source);
            //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
            X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));
            boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
            if (verify) {
                System.out.println("验签成功");
                // TODO: 业务处理
                PayResult result = JSON.parseObject(responseStr, PayResult.class);
                System.out.println("callbackurl:  " + callbackurl);
                if(!"000000".equals(result.getCode())){
                    throw new CustomException(result.getMsg());
                }

                Payorderinfo payorderinfo = new Payorderinfo();
                //保存发起信息
                payorderinfo.setOrderid(orderId);
                payorderinfo.setHyid(payorderinfo.getHyid());
                payorderinfo.setPaychannel("5");
                payorderinfo.setYwddidlx(ywtype);
                payorderinfo.setPaytype("W01");
                payorderinfo.setTrxamt(orderAmount);
                payorderinfo.setRemark(remark);
                payorderinfo.setNotifyurl(PAY_NOTIFY_URL);
                payorderinfo.setCsurl(null);
                //保存返回信息
                payorderinfo.setRetcode(String.valueOf(result.getCode()));
                payorderinfo.setRetmsg(result.getMsg());
                payorderinfo.setTrxid(result.getResp_data().getPay_order_no());
                payorderinfo.setChnltrxid(result.getResp_data().getPay_order_no());
                payorderinfo.setReqsn(orderIdReq);
                payorderinfo.setPayinfo(result.getResp_data().getCounter_url());
                payorderinfo.setXdsj(new Date());
                payorderinfo.setZfstatus("1");
                payorderinfo.setMa001(ma001);
                payorderinfo.setIsmainbody("0");
                payorderinfoMapper.insertPayorderinfo(payorderinfo);
                return payorderinfo;

            } else {
                System.err.println("验签失败");
                throw new CustomException("验签失败");
            }

        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("下单出现异常，请联系经销商！");
        }
    }

    @Override
    public Payorderinfo queryOrderPay(Long agencyid, String reqsn) {
        String merchant_no = marchentNo ;
        String term_no = termNo;
        SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
        String req_time = sdf_ts.format(new Date());
        String body = "{\n" +
                "    \"req_data\": {\n" +
                "        \"out_order_no\": \""+reqsn+"\", \n" +
                "        \"merchant_no\": \""+merchant_no+"\", \n" +
                "    }, \n" +
                "    \"version\": \"3.0\", \n" +
                "    \"req_time\": \""+req_time+"\"}";

        try {
            String authorization = getAuthorization(body);
            HttpResponse response = post(ORDER_QUERY_URL, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                String err = "请求失败，statusCode  " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING);
                System.out.println(err);
                throw new CustomException(err);
            }

            String appid = getHeadValue(response, "Lklapi-Appid");
            String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
            String timestamp = getHeadValue(response, "Lklapi-Timestamp");
            String nonce = getHeadValue(response, "Lklapi-Nonce");
            String signature = getHeadValue(response, "Lklapi-Signature");
            String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
            System.out.println("responseStr  " + responseStr);
            String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
            //System.out.println("source  " + source);
            //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
            X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));
            boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
            if (verify) {
                System.out.println("验签成功");
                // TODO: 业务处理
                PayResult result = JSON.parseObject(responseStr, PayResult.class);
                if(!"000000".equals(result.getCode())){
                    throw new CustomException(result.getMsg());
                }

                Payorderinfo payorderinfo = new Payorderinfo();
                //支付订单状态 0-订单生成 1-支付中 2-支付成功 3-支付失败 4-已撤销 5-已退款 6-订单关闭
                String zfstatus = "";
                String orderstatus = result.getResp_data().getOrder_status();
                //0:待支付 1:支付中 2:支付成功 3:支付失败 4:已过期 5:已取消 6:部分退款或者全部退款 7:订单已关闭枚举
                payorderinfo.setZfstatus(result.getResp_data().getOrder_status());
                payorderinfo.setErrmsg(result.getMsg());
                return payorderinfo;

            } else {
                System.err.println("验签失败");
                throw new CustomException("验签失败");
            }

        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("下单出现异常，请联系经销商！");
        }
    }

    @Override
    public Payreturninfo refundOrder(Long payorderinfoid, BigDecimal refundFee, String bz, String ip) {
        Payorderinfo payorderinfo = payorderinfoMapper.selectPayorderinfoById(payorderinfoid);

        if(StringUtils.isEmpty(payorderinfo.getZfstatus())){
            throw new CustomException("支付订单状态不正确");
        }
        if(!payorderinfo.getZfstatus().equals("2") && !payorderinfo.getZfstatus().equals("4")){
            throw new CustomException("支付订单状态不正确");
        }

        BigDecimal alreadyRefundFee = payorderinfo.getTkje()==null?BigDecimal.ZERO:payorderinfo.getTkje();
        BigDecimal allRefundFee = alreadyRefundFee.add(refundFee);
        if(allRefundFee.compareTo(new BigDecimal(payorderinfo.getTrxamt()))>0){
            throw new CustomException("退款金额不能大于支付金额");
        }

        String refundNo = payorderinfo.getPayid()+"-"+ payorderinfo.getYwddidlx()+"-"+payorderinfo.getOrderid() + "-" + UniqueIdGenerator.generate();

        String merchant_no =  appid ; 
        String term_no = "appkey";
        String refund_amount = String.valueOf((refundFee.multiply(new BigDecimal(100))).intValue());
        SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
        String req_time = sdf_ts.format(new Date());
        //小程序-主扫
        if("5".equals(payorderinfo.getYwddidlx()) || "6".equals(payorderinfo.getYwddidlx()) || "9".equals(payorderinfo.getYwddidlx()) ){
            String body = "{\n" +
                    "    \"req_data\": {\n" +
                    "        \"out_trade_no\": \""+refundNo+"\", \n" +
                    "        \"merchant_no\": \""+merchant_no+"\", \n" +
                    "        \"term_no\": \""+term_no+"\", \n" +
                    "        \"refund_amount\": \""+refund_amount+"\", \n" +
                    "        \"refund_reason\": \""+bz+"\", \n" +
                    "        \"origin_out_trade_no\": \""+payorderinfo.getReqsn()+"\", \n" +
                    "        \"location_info\": {\n" +
                    "            \"request_ip\": \""+ip+"\"\n" +
                    "        }   "+

                    "    }, \n" +
                    "    \"version\": \"3.0\", \n" +
                    "    \"req_time\": \""+req_time+"\"}";

            try {
                String authorization = getAuthorization(body);
                HttpResponse response = post(MINI_ORDER_REFUND_URL, body, authorization);
                if (response.getStatusLine().getStatusCode() != 200) {
                    String err = "请求失败，statusCode  " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING);
                    System.out.println(err);
                    throw new CustomException(err);
                }

                String appid = getHeadValue(response, "Lklapi-Appid");
                String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
                String timestamp = getHeadValue(response, "Lklapi-Timestamp");
                String nonce = getHeadValue(response, "Lklapi-Nonce");
                String signature = getHeadValue(response, "Lklapi-Signature");
                String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
                System.out.println("responseStr  " + responseStr);
                String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
                //System.out.println("source  " + source);
                //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
                X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));
                boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
                if (verify) {
                    System.out.println("验签成功");
                    // TODO: 业务处理
                    PayResult result = JSON.parseObject(responseStr, PayResult.class);

                    if(!"BBS00000".equals(result.getCode())){
                        throw new CustomException(result.getMsg());
                    }
                    Payreturninfo payreturninfo = new Payreturninfo();
                    payreturninfo.setHyid(payorderinfo.getHyid());
                    payreturninfo.setOrderpayid(payorderinfoid);
                    payreturninfo.setReqsn(payorderinfo.getReqsn());
                    payreturninfo.setRefundno(refundNo);
                    payreturninfo.setUniquerefundno(result.getResp_data().getTrade_no());
                    payreturninfo.setRefundfee(refundFee);
                    payreturninfo.setTksqsj(new Date());
                    payreturninfo.setTkwcsj(new Date());
                    payreturninfo.setNotifyurl(REFUND_NOTIFY_URL);
                    payreturninfo.setStatus("1");
                    //payreturninfo.setReturnfee(refundFee);
                    payreturninfo.setBz(bz);
                    payreturninfoMapper.insertPayreturninfo(payreturninfo);
                    payorderinfo.setZfstatus("4");
                    payorderinfo.setTkje(allRefundFee);
                    //BigDecimal tkfee = payorderinfo.getTkfee()==null?BigDecimal.ZERO:payorderinfo.getTkfee();
                    //payorderinfo.setTkfee(refundFee.add(tkfee));
                    payorderinfoMapper.updatePayorderinfo(payorderinfo);
                    return payreturninfo;

                } else {
                    System.err.println("验签失败");
                    throw new CustomException("验签失败");
                }

            }catch (Exception e){
                e.printStackTrace();
                throw new CustomException("下单出现异常，请联系经销商！");
            }
        }else{
            String body = "{\n" +
                    "    \"req_data\": {\n" +
                    "        \"out_trade_no\": \""+refundNo+"\", \n" +
                    "        \"merchant_no\": \""+merchant_no+"\", \n" +
                    "        \"term_no\": \""+term_no+"\", \n" +
                    "        \"refund_amount\": \""+refund_amount+"\", \n" +
                    "        \"refund_reason\": \""+bz+"\", \n" +
                    "        \"notify_url\": \""+REFUND_NOTIFY_URL+"\", \n" +
                    "        \"origin_log_no\": \""+payorderinfo.getChnltrxid()+"\", \n" +
                    "        \"origin_out_trade_no\": \""+payorderinfo.getReqsn()+"\", \n" +
                    //"        \"origin_trade_no\": \""+payorderinfo.getTrxid()+"\", \n" +
                    "        \"location_info\": {\n" +
                    "            \"request_ip\": \""+ip+"\"\n" +
                    "        }   "+

                    "    }, \n" +
                    "    \"version\": \"3.0\", \n" +
                    "    \"req_time\": \""+req_time+"\"}";

            try {
                String authorization = getAuthorization(body);
                HttpResponse response = post(ORDER_REFUND_URL, body, authorization);
                if (response.getStatusLine().getStatusCode() != 200) {
                    String err = "请求失败，statusCode  " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING);
                    System.out.println(err);
                    throw new CustomException(err);
                }

                String appid = getHeadValue(response, "Lklapi-Appid");
                String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
                String timestamp = getHeadValue(response, "Lklapi-Timestamp");
                String nonce = getHeadValue(response, "Lklapi-Nonce");
                String signature = getHeadValue(response, "Lklapi-Signature");
                String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
                System.out.println("responseStr  " + responseStr);
                String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
                //System.out.println("source  " + source);
                //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
                X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));
                boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
                if (verify) {
                    System.out.println("验签成功");
                    // TODO: 业务处理
                    PayResult result = JSON.parseObject(responseStr, PayResult.class);

                    if(!"000000".equals(result.getCode())){
                        throw new CustomException(result.getMsg());
                    }
                    Payreturninfo payreturninfo = new Payreturninfo();
                    if("INIT".equals(result.getResp_data().getTrade_state()) ||
                            "SUCCESS".equals(result.getResp_data().getTrade_state()) ||
                            "FAIL".equals(result.getResp_data().getTrade_state()) ||
                            "DEAL".equals(result.getResp_data().getTrade_state()) ||
                            "TIMEOUT".equals(result.getResp_data().getTrade_state())
                    ){
                        payreturninfo.setHyid(payorderinfo.getHyid());
                        payreturninfo.setOrderpayid(payorderinfoid);
                        payreturninfo.setReqsn(payorderinfo.getReqsn());
                        payreturninfo.setRefundno(refundNo);
                        payreturninfo.setUniquerefundno(result.getResp_data().getTrade_no());
                        payreturninfo.setRefundfee(refundFee);
                        payreturninfo.setTksqsj(new Date());
                        payreturninfo.setTkwcsj(new Date());
                        payreturninfo.setNotifyurl(REFUND_NOTIFY_URL);
                        if("SUCCESS".equals(result.getResp_data().getOrder_status())){
                            payreturninfo.setStatus("1");
                        }else{
                            payreturninfo.setStatus("0");
                        }
                        //payreturninfo.setReturnfee(refundFee);
                        payreturninfo.setBz(bz);
                        payreturninfoMapper.insertPayreturninfo(payreturninfo);

                        payorderinfo.setZfstatus("4");
                        payorderinfo.setTkje(allRefundFee);
                        //BigDecimal tkfee = payorderinfo.getTkfee()==null?BigDecimal.ZERO:payorderinfo.getTkfee();
                        //payorderinfo.setTkfee(refundFee.add(tkfee));
                        payorderinfoMapper.updatePayorderinfo(payorderinfo);
                        return payreturninfo;
                    }else{
                        throw new CustomException(result.getMsg());
                    }

                } else {
                    System.err.println("验签失败");
                    throw new CustomException("验签失败");
                }

            }catch (Exception e){
                e.printStackTrace();
                throw new CustomException("下单出现异常，请联系经销商！");
            }
        }
    }


    public boolean verifyData(HttpServletRequest request, String responseStr){
        System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        //String authorization =request.getHeader("Authorization");
        String authorization ="LKLAPI-SHA256withRSA timestamp=\"1737539848\",nonce_str=\"jBXECZVhE4rv\",signature=\"GdwnWX2iXUAEnKFm3cHHm/wjAiwvNvFo6HzftbhPjr6u8vdK63XOGmpygEWkTnNuvbuqi0DLksOF0IgT6N2YkqXJvmDSdB74nA8hKBXX/e1MUCFaXVDk/TVKi5aEvz3QdiHHyOMjEPVObZtSdo29Sre6+XRXqvID7dgmSddtuCR7hXQVU2vT5/haCouFNH2QO1gXBLzz/Q1+Svhb+4838aJp3e/OJTHYEFRKZyPUJmd0v1InLCC9GpsJcQJfcB6qpQ65IIl9+ZslNA+XpKaG/2vgq295qDuxOI98ZsDXN9rZILYflaVXWcECFT2oE4uMXwjlNrL+ExwPmLpk9LkAwQ==\"";
        // 解析 Authorization 字符串
        String[] parts = authorization.replace(SCHEMA + " ", "").split(",");
        String timestamp = "";
        String nonce = "";
        String signature = "";

        for (String part : parts) {
            if (part.contains("timestamp")) {
                timestamp = part.split("=")[1].replace("\"", "").trim();
            } else if (part.contains("nonce_str")) {
                nonce = part.split("=")[1].replace("\"", "").trim();
            } else if (part.contains("signature")) {
                signature = part.split("=", 2)[1].replace("\"", "").trim();            }
        }

        System.out.println("timestamp=" + timestamp);
        System.out.println("nonce=" + nonce);
        System.out.println("signature=" + signature);

        String preSignData = timestamp +"\n" + nonce + "\n" +responseStr + "\n";

        //String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
        //String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
        //System.out.println("source  " + source);
        //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
        X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));
        try {
            boolean verify = verify(lklCertificate, preSignData.getBytes(ENCODING), signature);
            return verify;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static void main3(String[] args) {
        LaKaLaPayService demo = new LaKaLaPayService();
        demo.verifyData(null,"{\"channel_id\":\"95\",\"merchant_no\":\"82245205999074C\",\"order_create_time\":\"20250122165358\",\"order_effi\n" +
                "cient_time\":\"20250129165358\",\"order_info\":\"交易扫码付款\",\"order_status\":\"2\",\"order_trade_info\":{\"acc_discount_amount\":\"0\n" +
                "\",\"acc_mdiscount_amount\":\"0\",\"acc_other_discount_amount\":\"\",\"acc_settle_amount\":\"1\",\"acc_trade_no\":\"42000026222025012200\n" +
                "57573028\",\"acc_type\":\"02\",\"bank_type\":\"OTHERS\",\"busi_type\":\"SCPAY\",\"log_no\":\"66221291550478\",\"pay_mode\":\"WECHAT\",\"payer_\n" +
                "amount\":1,\"settle_merchant_no\":\"82245205999074C\",\"settle_term_no\":\"M0893382\",\"trade_amount\":1,\"trade_no\":\"20250122110113\n" +
                "130266221291550478\",\"trade_remark\":\"\",\"trade_status\":\"S\",\"trade_time\":\"20250122165407\",\"trade_type\":\"PAY\",\"user_id1\":\"o0\n" +
                "eL86kBbSmu9KADCBsHS5VQTE0U\",\"user_id2\":\"oVxsc1XspNQiopnbJWAqhNxE1IHU\"},\"out_order_no\":\"754-7-3381762-1000001035658186\",\"\n" +
                "pay_order_no\":\"25012211012001101011307867654\",\"term_no\":\"M0893382\",\"total_amount\":1,\"trans_merchant_no\":\"82245205999074C\n" +
                "\",\"trans_term_no\":\"M0893382\"}");
    }

    public static void main2(String[] args) {
        try {
            LaKaLaPayService demo = new LaKaLaPayService();
            String orderNo = String.valueOf(System.currentTimeMillis());
            SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
            String order_efficient_time = sdf_ts.format(DateUtils.addDays(new Date(),7));
            String req_time = sdf_ts.format(new Date());
            String merchant_no = "82245205999074C";
            String term_no = "M0893382";
            String body = "{\n" +
                    "    \"req_data\": {\n" +
                    "        \"out_order_no\": \""+orderNo+"\", \n" +
                    "        \"merchant_no\": \""+merchant_no+"\", \n" +
                    "        \"term_no\": \""+term_no+"\", \n" +
                    "        \"channel_id\": \"\", \n" +
                    "        \"total_amount\": \"1\", \n" +
                    "        \"order_efficient_time\": \""+order_efficient_time+"\", \n" +
                    "        \"notify_url\": \""+PAY_NOTIFY_URL+"\", \n" +
                    "        \"support_cancel\": \"0\", \n" +
                    "        \"support_refund\": \"1\", \n" +
                    "        \"support_repeat_pay\": \"0\", \n" +
                    "        \"order_info\": \"测试商品\", \n" +
                    "        \"extend_info\": \"\", \n" +
                    "        \"callback_url\": \"\"\n" +
                    "    }, \n" +
                    "    \"version\": \"3.0\", \n" +
                    "    \"req_time\": \""+req_time+"\"}";

            String authorization = demo.getAuthorization(body);
            HttpResponse response = demo.post(ORDER_PAY_URL, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                System.out.println("请求失败，statusCode  " + response.getStatusLine()
                        + IOUtils.toString(response.getEntity().getContent(), ENCODING));
                return;
            }

            String appid = getHeadValue(response, "Lklapi-Appid");
            String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
            String timestamp = getHeadValue(response, "Lklapi-Timestamp");
            String nonce = getHeadValue(response, "Lklapi-Nonce");
            String signature = getHeadValue(response, "Lklapi-Signature");
            String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);

            System.out.println("responseStr  " + responseStr);

            String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";

            //System.out.println("source  " + source);

            //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
            X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));

            boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);

            if (verify) {
                System.out.println("验签成功");

                // TODO: 业务处理


            } else {
                System.err.println("验签失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main4(String[] args) {
        try {
            LaKaLaPayService demo = new LaKaLaPayService();
            String orderIdReq = String.valueOf(System.currentTimeMillis());
            SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
            String order_efficient_time = sdf_ts.format(DateUtils.addDays(new Date(),7));
            String req_time = sdf_ts.format(new Date());
            String merchant_no = "82245205999074Y";
            String term_no = "M1028210";
            String body = "{\n" +
                    "    \"req_data\": {\n" +
                    "        \"out_trade_no\": \""+orderIdReq+"\", \n" +
                    "        \"merchant_no\": \""+merchant_no+"\", \n" +
                    "        \"term_no\": \""+term_no+"\", \n" +
                    "        \"account_type\": \"WECHAT\", \n" +
                    "        \"trans_type\": \"71\", \n" +
                    "        \"location_info\": {\n" +
                    "            \"request_ip\": \""+"119.167.17.169"+"\"\n" +
                    "        },   "+
                    "        \"total_amount\": \""+1+"\", \n" +
                    "        \"notify_url\": \""+MINI_PAY_NOTIFY_URL+"\", \n" +
                    "        \"subject\": \""+"测试商品"+"\", \n" +

                    "        \"acc_busi_fields\": {\n" +
                    "            \"sub_appid\": \"wx29691bdaf7326869\",\n" +
                    "            \"user_id\": \""+"of_Ir5C3IBi1o3jcBvkGuw3So9wM"+"\"\n" +
                    "        }   "+

                    "    }, \n" +
                    "    \"version\": \"3.0\", \n" +
                    "    \"req_time\": \""+req_time+"\"}";

            String authorization = demo.getAuthorization(body);
            HttpResponse response = demo.post(MINI_ORDER_PAY_URL, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                System.out.println("请求失败，statusCode  " + response.getStatusLine()
                        + IOUtils.toString(response.getEntity().getContent(), ENCODING));
                return;
            }

            String appid = getHeadValue(response, "Lklapi-Appid");
            String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
            String timestamp = getHeadValue(response, "Lklapi-Timestamp");
            String nonce = getHeadValue(response, "Lklapi-Nonce");
            String signature = getHeadValue(response, "Lklapi-Signature");
            String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);

            System.out.println("responseStr  " + responseStr);

            String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";

            //System.out.println("source  " + source);

            //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
            X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));

            boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);

            if (verify) {
                System.out.println("验签成功");

                // TODO: 业务处理


            } else {
                System.err.println("验签失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {

        LaKaLaPayService demo = new LaKaLaPayService();
        String orderIdReq = String.valueOf(System.currentTimeMillis());
        SimpleDateFormat sdf_ts = new SimpleDateFormat("yyyyMMddHHmmss");
        String order_efficient_time = sdf_ts.format(DateUtils.addDays(new Date(),7));
        String req_time = sdf_ts.format(new Date());

        String merchant_no = "82245205999074Y";
        String term_no = "M1028929";

        String body = "{\n" +
                "    \"req_data\": {\n" +
                "        \"out_trade_no\": \""+orderIdReq+"\", \n" +
                "        \"merchant_no\": \""+merchant_no+"\", \n" +
                "        \"term_no\": \""+term_no+"\", \n" +
                "        \"refund_amount\": \""+"1"+"\", \n" +
                "        \"refund_reason\": \""+"备注"+"\", \n" +
                "        \"notify_url\": \""+REFUND_NOTIFY_URL+"\", \n" +
                "        \"origin_log_no\": \""+"66221296317492"+"\", \n" +
                "        \"origin_out_trade_no\": \""+"754-7-3382139-1000001436349643"+"\", \n" +
                //"        \"origin_trade_no\": \""+"25012311012001101011308518931"+"\", \n" +
                "        \"location_info\": {\n" +
                "            \"request_ip\": \""+"127.0.0.1"+"\"\n" +
                "        }   "+

                "    }, \n" +
                "    \"version\": \"3.0\", \n" +
                "    \"req_time\": \""+req_time+"\"}";

            System.out.println(body);
        String authorization = demo.getAuthorization(body);
        HttpResponse response = demo.post(ORDER_REFUND_URL, body, authorization);
        if (response.getStatusLine().getStatusCode() != 200) {
            System.out.println("请求失败，statusCode  " + response.getStatusLine()
                    + IOUtils.toString(response.getEntity().getContent(), ENCODING));
            return;
        }

        String appid = getHeadValue(response, "Lklapi-Appid");
        String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
        String timestamp = getHeadValue(response, "Lklapi-Timestamp");
        String nonce = getHeadValue(response, "Lklapi-Nonce");
        String signature = getHeadValue(response, "Lklapi-Signature");
        String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);

        System.out.println("responseStr  " + responseStr);

        String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";

        //System.out.println("source  " + source);

        //X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
        X509Certificate lklCertificate = loadCertificate(LaKaLaPayService.class.getResourceAsStream(lklCertificatePath));

        boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);

        if (verify) {
            System.out.println("验签成功");

            // TODO: 业务处理


        } else {
            System.err.println("验签失败");
        }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public HttpResponse post(String url, String message, String authorization) throws Exception {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] xcs, String str) {}
            public void checkServerTrusted(X509Certificate[] xcs, String str) {}
        };
        HttpClient http = new DefaultHttpClient();
        ClientConnectionManager ccm = http.getConnectionManager();
        ctx.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        SchemeRegistry registry = ccm.getSchemeRegistry();
        registry.register(new Scheme("https", ssf,443));
        HttpPost post = new HttpPost(url);
        StringEntity myEntity = new StringEntity(message, ENCODING);
        post.setEntity(myEntity);
        post.setHeader("Authorization", SCHEMA + " " + authorization);
        post.setHeader("Accept", "application/json");
        post.setHeader("Content-Type", "application/json");
        return http.execute(post);
    }

    protected long generateTimestamp() {
        return System.currentTimeMillis() / 1000;
    }

    protected String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }

    public final String getAuthorization(String body) throws IOException {
        String nonceStr = generateNonceStr();
        long timestamp = generateTimestamp();

        String message = appid + "\n" + mchSerialNo + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";

        //System.out.println("getToken message :  " + message);

        //PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(new File(merchantPrivateKeyPath)));
        PrivateKey merchantPrivateKey = loadPrivateKey(LaKaLaPayService.class.getResourceAsStream(merchantPrivateKeyPath));

        String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey);

        String authorization = "appid=\"" + appid + "\"," + "serial_no=\"" + mchSerialNo + "\"," + "timestamp=\""
                + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\"";
        //System.out.println("authorization message :" + authorization);

        return authorization;
    }

    public String sign(byte[] message, PrivateKey privateKey) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            return new String(Base64.encodeBase64(sign.sign()));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名计算失败", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的私钥", e);
        }
    }

    private static String getHeadValue(HttpResponse response, String key) {
        return (response.containsHeader(key)) ? response.getFirstHeader(key).getValue() : "";
    }

    private static boolean verify(X509Certificate certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(message);
            byte[] signatureB = Base64.decodeBase64(signature);
            return sign.verify(signatureB);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }

    public static PrivateKey loadPrivateKey(InputStream inputStream) {
        try {
            ByteArrayOutputStream array = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                array.write(buffer, 0, length);
            }
            String privateKey = array.toString("utf-8").replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥");
        }
    }

    public static X509Certificate loadCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);

            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }

}
